﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using t_TestingLibrary;
using CDSParser;
using PaperRenderingInterfaces;
using System.ComponentModel.Composition;
using System.IO;
using System.Drawing;
using System.Threading.Tasks;
using DeepZoomPivotConstructor.PivotLib;

namespace t_CDSPaperFigureExtractor
{
    [TestClass]
    public class t_CDSFiguresFromOnePaper
    {
        [TestInitialize]
        public void TestSetup()
        {
            Utilities.MyClassInit();
        }

        [TestCleanup]
        public void TestCleanup()
        {
            Utilities.MyClassDone();
        }

        [TestMethod]
        public void TestCtor()
        {
            CDSFiguresFromOnePaper p = new CDSFiguresFromOnePaper();
        }

        /// <summary>
        /// Load a file instead of accessing the web.
        /// </summary>
        [Export(typeof(IWebAccess))]
        private class LoadAFile : IWebAccess
        {
            public FileInfo theFileToLoadMARC;
            public FileInfo theFileToLoadDC;
            public string UrlAskedFor { get; set; }

            public string GetUriAsString(Uri whatToLoad)
            {
                UrlAskedFor = whatToLoad.OriginalString;

                if (whatToLoad.OriginalString.EndsWith("xm"))
                {
                    return LoadFile(theFileToLoadMARC);
                }
                else
                {
                    return LoadFile(theFileToLoadDC);
                }
            
                throw new NotImplementedException();
            }

            /// <summary>
            /// Load up the req' file.
            /// </summary>
            /// <param name="finfo"></param>
            /// <returns></returns>
            private string LoadFile(FileInfo finfo)
            {
                if (finfo.Exists)
                {
                    using (var reader = finfo.OpenText())
                    {
                        return reader.ReadToEnd();
                    }
                }
                else
                {
                    return null;
                }
            }


            public DateTime? GetLastModificationTime(Uri whatToCheck)
            {
                throw new NotImplementedException();
            }
        }

        /// <summary>
        /// Dummy renderer for an image that we grab
        /// </summary>
        [Export(typeof(RenderEngineInterfaces.IRenderItem))]
        [RenderEngineInterfaces.RenderInfo(typeof(Uri))]
        public class RenderUri : RenderEngineInterfaces.IRenderItem, RenderEngineInterfaces.IRenderableObjectCompare
        {
            public Task<DeepZoomPivotConstructor.VisualLib.Visual> Render(object what)
            {
                return Task<DeepZoomPivotConstructor.VisualLib.Visual>.Factory.StartNew(() => new DeepZoomPivotConstructor.VisualLib.VisualBitmapImage(2.0, 1.0, 100, Color.Black));
            }

            public RenderEngineInterfaces.RenderPluginPriority RenderPriority(object what)
            {
                if ((what as Uri) != null)
                {
                    return RenderEngineInterfaces.RenderPluginPriority.RPPGeneric;
                }
                else
                {
                    return RenderEngineInterfaces.RenderPluginPriority.RPPCantDoIt;
                }
            }

            public int GetObjectHash(object what)
            {
                return 5000;
            }

            public bool ObjectsEqual(object o1, object o2)
            {
                throw new NotImplementedException();
            }

            public bool IsOutOfDate(object what, object metaData)
            {
                throw new NotImplementedException();
            }

            public object GetObjectDateMetaData(object what)
            {
                return null;
            }
        }
        
        [TestMethod]
        public void TestPaperNoFigures()
        {
            var result = LoadImages("1228922");
            Assert.AreEqual(0, result.Count(), "Expected nothing back for that paper!");
        }

        [TestMethod]
        public void TestPaperWithFigures()
        {
            var result = LoadImages("1198228");
            Assert.AreEqual(14, result.Count(), "Expected nothing back for that paper!");

            ///
            /// Check some of the assoicated meta data on the figures now
            /// 

            PivotImage pmf = result.First();
            Assert.IsTrue(pmf.Name.StartsWith("Figure"), "The name isn't correct");
            Assert.IsTrue(pmf.Description.StartsWith("No Description provided - note abstract: "), "The description isn't right either");
            Assert.IsTrue(pmf.Count() > 0, "Expected some meta data associated with the pivot guy!");
            var lnk = FindMetadata<PivotMetadataURL>(pmf, "Graphics Files");
            Assert.AreEqual(1, lnk.Count(), "Expected at 1 graphics file!");
            var lnk1 = FindMetadata<PivotMetadataString>(pmf, "Caption");
            Assert.AreEqual(1, lnk1.Count(), "Expected a caption!");
            var lnk2 = FindMetadata<PivotMetadataDateTime>(pmf, "Date");
            Assert.AreEqual(1, lnk2.Count(), "Expected a date!");
            lnk = FindMetadata<PivotMetadataURL>(pmf, "More Information");
            Assert.AreEqual(2, lnk.Count(), "Expected a more info link (both direct PDF and also the CDS page)!");
            var lnk3 = FindMetadata<PivotMetadataString>(pmf, "Note Title");
            Assert.AreEqual(1, lnk3.Count(), "Expected a note title!");
        }

        [TestMethod]
        public void TestPaperWithNoAbstract()
        {
            var result = LoadImages("1194487");

            ///
            /// make sure that we have a pretty short description now!
            /// 

            PivotImage pmf = result.First();
            Assert.AreEqual("No Description or abstract provided", pmf.Description, "Bad description");

        }

        [TestMethod]
        public void TestPaperNoteDirectLink()
        {
            var result = LoadImages("1194487");

            PivotImage pmf = result.First();
            var links = from md in pmf
                        where md.Name == "More Information"
                        let mklnk = md as PivotMetadataURL
                        where mklnk != null && mklnk.LinkText == "Note"
                        select mklnk;
            var link = links.FirstOrDefault();
            Assert.IsNotNull(link, "Found no note link!!");
            Assert.AreEqual("http://cdsweb.cern.ch/record/1194487/files/PFT-09-001-pas.pdf", link.LinkUri.OriginalString, "Link is incorrect!");
        }

        [TestMethod]
        public void TestPublishedCMSPaper()
        {
            var result = LoadImages("1237408");
            Assert.AreEqual(14, result.Count(), "Incorrect number of figures detected from the article!");

            var pi = result.First();
            Assert.IsTrue(pi.Description.Contains("Measurements of inclusive charged-hadron"), "The caption doesn't have the abstract... odd!");
            var lnk = FindMetadata<PivotMetadataURL>(pi, "More Information");
            Assert.AreEqual(2, lnk.Count(), "Expected a more info link (both direct PDF and also the CDS page)!");
        }

        private static IEnumerable<PivotImage> LoadImages(string name)
        {
            CDSFiguresFromOnePaper target = new CDSFiguresFromOnePaper();
            var laf = new LoadAFile()
            {
                theFileToLoadMARC = new FileInfo("..\\..\\..\\t_CDSParser\\" + name + ".xml"),
                theFileToLoadDC = new FileInfo("..\\..\\..\\t_CDSParser\\" + name + "-DC.xml")
            };
            Utilities.AddPart(laf);
            Utilities.AddPart(new RenderUri());
            Utilities.AddPart(new RenderEngine.RenderControl());
            Utilities.Compose(target);
            var result = target.Render(name);

            Assert.AreEqual("http://cdsweb.cern.ch/record/" + name + "/export/xd", laf.UrlAskedFor, "The request URL didn't work right!");

            return result;
        }

        /// <summary>
        /// Hunt throught the metadata!
        /// </summary>
        /// <typeparam name="T1"></typeparam>
        /// <param name="pmf"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        private T1[] FindMetadata<T1>(PivotImage pmf, string p)
            where T1 : PivotMetadataBase
        {
            var md = from m in pmf
                     where m.Name == p && m.GetType() == typeof(T1)
                     let masType = (T1) m
                     where masType != null
                     select masType;
            return md.ToArray();
        }
    }
}
